/**
 * 纸张尺寸单位类型
 */
export type PaperSizeUnit = "mm" | "cm" | "inch" | "px";

/**
 * 纸张方向类型
 */
export type PaperOrientation = "portrait" | "landscape";

/**
 * 纸张尺寸接口
 */
export interface PaperSize {
	width: number;
	height: number;
	unit: PaperSizeUnit;
	orientation: PaperOrientation;
}

/**
 * 屏幕DPI（每英寸点数）配置接口
 */
export interface DpiConfig {
	default?: number;
	x?: number;
	y?: number;
}

/**
 * A系列纸张尺寸计算器
 */
export default class PaperSizeCalculator {
	// A系列纸张基础尺寸（A0尺寸，单位：毫米）
	private static readonly A0_WIDTH_MM = 841;
	private static readonly A0_HEIGHT_MM = 1189;

	// 单位转换常量
	private static readonly MM_TO_INCH = 1 / 25.4;
	private static readonly INCH_TO_MM = 25.4;
	private static readonly CM_TO_MM = 10;

	// 屏幕DPI（默认96）
	private dpi: { x: number; y: number };

	constructor(dpiConfig: DpiConfig = { default: 96 }) {
		this.dpi = {
			x: dpiConfig.x || dpiConfig.default || 96,
			y: dpiConfig.y || dpiConfig.default || 96,
		};
	}

	static toFixed(num: number, fixed: number) {
		return Number(num.toFixed(fixed));
	}

	/**
	 * 获取标准A系列纸张尺寸（毫米单位）
	 * @param size 纸张大小（A3, A4, A5等）
	 * @returns 包含宽高的对象（毫米单位）
	 */
	getStandardSizeInMM(size: "A3" | "A4" | "A5"): { width: number; height: number } {
		// 计算A系列纸张的级数
		const level = parseInt(size.substring(1));
		const steps = level; // A0到An的步数

		// 计算尺寸（每次对折长边）
		let width = PaperSizeCalculator.A0_WIDTH_MM;
		let height = PaperSizeCalculator.A0_HEIGHT_MM;

		for (let i = 0; i < steps; i++) {
			const newWidth = height / 2;
			const newHeight = width;
			width = newWidth;
			height = newHeight;
		}

		return { width, height };
	}

	/**
	 * 单位转换
	 * @param value 值
	 * @param fromUnit 原始单位
	 * @param toUnit 目标单位
	 * @param isWidth 是否是宽度（用于DPI不同时）
	 * @returns 转换后的值
	 */
	private convertUnit(value: number, fromUnit: PaperSizeUnit, toUnit: PaperSizeUnit, isWidth: boolean = true): number {
		if (fromUnit === toUnit) return value;

		// 先转换为毫米
		let valueInMM = value;
		switch (fromUnit) {
			case "cm":
				valueInMM = value * PaperSizeCalculator.CM_TO_MM;
				break;
			case "inch":
				valueInMM = value * PaperSizeCalculator.INCH_TO_MM;
				break;
			case "px":
				valueInMM = (value / (isWidth ? this.dpi.x : this.dpi.y)) * PaperSizeCalculator.INCH_TO_MM;
				break;
		}

		// 从毫米转换为目标单位
		switch (toUnit) {
			case "mm":
				return valueInMM;
			case "cm":
				return valueInMM / PaperSizeCalculator.CM_TO_MM;
			case "inch":
				return valueInMM * PaperSizeCalculator.MM_TO_INCH;
			case "px":
				return valueInMM * PaperSizeCalculator.MM_TO_INCH * (isWidth ? this.dpi.x : this.dpi.y);
			default:
				throw new Error(`Unsupported unit: ${toUnit}`);
		}
	}

	/**
	 * 获取纸张尺寸
	 * @param size 纸张大小（A3, A4, A5）
	 * @param unit 单位（默认毫米）
	 * @param orientation 方向（默认纵向）
	 * @returns 纸张尺寸对象
	 */
	getPaperSize(size: "A3" | "A4" | "A5", unit: PaperSizeUnit = "mm", orientation: PaperOrientation = "portrait"): PaperSize {
		// 获取标准尺寸（毫米）
		const { width: widthMM, height: heightMM } = this.getStandardSizeInMM(size);

		// 根据方向确定宽高
		let width = orientation === "portrait" ? widthMM : heightMM;
		let height = orientation === "portrait" ? heightMM : widthMM;

		// 转换为目标单位
		width = this.convertUnit(width, "mm", unit, true);
		height = this.convertUnit(height, "mm", unit, false);

		return {
			width,
			height,
			unit,
			orientation,
		};
	}

	/**
	 * 设置屏幕DPI
	 * @param dpi 新的DPI配置
	 */
	setDpi(dpi: DpiConfig): void {
		this.dpi = {
			x: dpi.x || dpi.default || this.dpi.x,
			y: dpi.y || dpi.default || this.dpi.y,
		};
	}

	/**
	 * 获取当前DPI配置
	 * @returns 当前DPI配置
	 */
	getDpi(): { x: number; y: number } {
		return { ...this.dpi };
	}
}
